package com.goodfox.web.generic.authority.filter;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.RegexUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;
import org.springframework.stereotype.Service;

import com.goodfox.web.generic.authority.entity.Resources;
import com.goodfox.web.generic.authority.service.ResourcesService;
import com.goodfox.web.generic.role.entity.Role;

/***
 * 重写spring security框架资源过滤器
 * @author qin gt
 *
 */
@Service(value="securityMetadataSource")
public class SecurityMetadataSourceImpl implements FilterInvocationSecurityMetadataSource, InitializingBean  {

	/** log4j日志器 */
	private Logger logger=Logger.getLogger(SecurityMetadataSourceImpl.class);
	
	/** 资源Service */
	private ResourcesService resourcesService;

	/** url匹配 */
    private UrlMatcher urlMatcher; 
    
	/** 是否自动构建路径 */
    private boolean bUseAntPath = true;
    
	/** 是否使用大小写转换 */ 
    private boolean bLowerCase = true;  

	/** 资源Map */
    public static Map<String, Collection<ConfigAttribute>> resourcesMap = null;  
	
	public SecurityMetadataSourceImpl(ResourcesService resourcesService) {  
		super();
		this.resourcesService=resourcesService;
        loadResourceDefine();  
    }
    
	/**
	 * 加载所有资源
	 */
    public void loadResourceDefine() { 
        resourcesMap = new HashMap<String, Collection<ConfigAttribute>>();
        List<Resources> rseList = resourcesService.queryResourcesList();   
        for (Resources rse:rseList) { 
            Collection<ConfigAttribute> attributes = new ArrayList<ConfigAttribute>();
            for (Role role:rse.getRoleList()) {    
                ConfigAttribute attribute = new SecurityConfig(role.getRolePower());   
                attributes.add(attribute);   
            }
            if(rse.getRseState().equals("1")){
            	resourcesMap.put(rse.getRseUrl(), attributes);
            }
        }   
        logger.debug("系统角色资源：");
        logger.debug(resourcesMap);
    }  
    
    /**
     * url构建
     */
	@Override
	public void afterPropertiesSet() throws Exception {
		this.urlMatcher = new RegexUrlPathMatcher();   
        if (bUseAntPath) {   
            urlMatcher = new AntUrlPathMatcher();   
        }   
        if (bLowerCase) {   
            if (!bUseAntPath) {   
                ((RegexUrlPathMatcher)urlMatcher).setRequiresLowerCaseUrl(true);   
            }   
        } else if (!bLowerCase) {   
            if (bUseAntPath) {   
                ((AntUrlPathMatcher)urlMatcher).setRequiresLowerCaseUrl(false);   
            }   
        }   
	}

    /**
     * 比较资源定义中的URL和当前请求的URL 
     */
	@Override
	public Collection<ConfigAttribute> getAttributes(Object filter)throws IllegalArgumentException {
		FilterInvocation filterInvocation = (FilterInvocation)filter;   
        String requestURI = filterInvocation.getRequestUrl();
        Iterator<String> terator = resourcesMap.keySet().iterator(); 
        while (terator.hasNext()) {  
            String resoruceURL = terator.next();    
            /**
             * resoruceURL 资源定义中的URL 
             * requestURL 当前请求的URL  
             */
            if (urlMatcher.pathMatchesUrl(resoruceURL, requestURI)) {   
                Collection<ConfigAttribute> attributes = resourcesMap.get(resoruceURL);   
                String colRole = "";   
                for (ConfigAttribute attribute : attributes) {  
                    colRole = colRole + "," + attribute.toString();   
                }   
                if (colRole.length() > 1) {   
                    colRole = colRole.substring(1);   
                }    
                return attributes;   
            }   
        }   
  
        return null;   
	}
	
	@Override
	public Collection<ConfigAttribute> getAllConfigAttributes() {
		return new ArrayList<ConfigAttribute>();
	}

	@Override
	public boolean supports(Class<?> arg0) {
		return true;
	}

	/** getter&setter start */

	public boolean isbUseAntPath() {
		return bUseAntPath;
	}

	public void setbUseAntPath(boolean bUseAntPath) {
		this.bUseAntPath = bUseAntPath;
	}

	public boolean isbLowerCase() {
		return bLowerCase;
	}

	public void setbLowerCase(boolean bLowerCase) {
		this.bLowerCase = bLowerCase;
	}
	
	public ResourcesService getResourcesService() {
		return resourcesService;
	}

	public void setResourcesService(ResourcesService resourcesService) {
		this.resourcesService = resourcesService;
	}

	/** getter&setter end */
}
